<?php


use App\Exceptions\BaseException;
use App\Kuafu\Base\Enum\BaseCodeEnum;
use App\Library\FeiShu\SendFs;
use GuzzleHttp\Psr7\Uri;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Kuafu\File\FileUtil;
use Kuafu\File\PrivateFileUtil;
use Kuafu\GeneralFs\BuildFs;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Psr\Http\Message\UriInterface;

if (!function_exists('getQueryInUrl')) {

    /**
     * 获取url中的get参数
     * @param string $url
     * @return array
     */
    function getQueryInUrl(string $url): array
    {
        $query = parse_url($url, PHP_URL_QUERY);
        parse_str($query, $params);

        return $params;
    }
}

if (!function_exists('checkUrl')) {

    /**
     * 获取url中的get参数
     * @param string $url
     * @return array
     */
    function checkUrl(string $url = ''): bool
    {
        $regex = '/^(http|https|ftp):\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\’:+!]*([^<>\”])*$/';
        if (preg_match($regex, $url)) {
            return true;
        } else {
            return false;
        }
    }
}

if (!function_exists('ossPublicFilePath')) {
    /**
     * @param string $path
     * @return string
     */
    function ossPublicFilePath(string $path = ''): string
    {
        return empty($path) ? "" : (preg_match("/^http(s)?:\\/\\/.+/", $path,
            $matches) ? $path : FileUtil::domain() . '/' . ltrim($path,
                '/'));
    }
}

if (!function_exists('ossPublicRelativeFilePath')) {
    /**
     * @param string $path
     * @return string
     */
    function ossPublicRelativeFilePath(string $path = ''): string
    {
        return str_replace(FileUtil::domain(), '', $path);
    }
}


if (!function_exists('privateFilePath')) {
    /**
     * @param string $path
     * @return string
     */
    function privateFilePath(string $path = '', string $style = ''): string
    {
        $options = null;
        if ($style) {
            $options = [
                \OSS\OssClient::OSS_PROCESS => $style,
            ];
        }

        try {
            return empty($path) ? "" : \Kuafu\File\PrivateFileUtil::signUrl($path, $timeout = 86400, $public = true,
                $method = 'GET', $options);
        } catch (Exception $exception) {
            return picturePath($path);
        }
    }
}


if (!function_exists('tigerPicturePath')) {
    /**
     * @param string $path
     * @return string
     */
    function tigerPicturePath(string $path = ''): string
    {
        return empty($path) ? "" : (preg_match("/^http(s)?:\\/\\/.+/", $path,
            $matches) ? $path : FileUtil::domain() . '/' . ltrim($path,
                '/'));
    }
}


if (!function_exists('tigerPrivateFilePath')) {
    /**
     * @param string $path
     * @return string
     */
    function tigerPrivateFilePath(string $path = ''): string
    {
        try {
            return empty($path) ? "" : PrivateFileUtil::signUrl($path);
        } catch (Exception $exception) {
            return picturePath($path);
        }
    }
}

if (!function_exists("getFileKey")) {
    /**
     * 获取私有文件key
     *
     * @param string $fileFullUrl
     * @return string
     * @throws Exception
     */
    function getFileKey(string $fileFullUrl): string
    {
        try {
            return trim(parse_url($fileFullUrl)["path"], "/");
        } catch (Exception $exception) {
            throw new Exception("获取文件key失败");
        }
    }
}


if (!function_exists('picturePath')) {
    /**
     * @param string $path
     * @return string
     */
    function picturePath(string $path = ''): string
    {
        if (str_starts_with($path, "http")) {
            return $path;
        } else {
            return empty($path) ? "" : rtrim(config("other.IMAGE_URL"), '/') . "/" . ltrim($path, '/');
        }
    }
}

if (!function_exists("getPicturePath")) {
    /**
     * 获取文件key
     *
     * @param string $fileFullUrl
     * @return string
     */
    function getPicturePath(string $fileFullUrl): string
    {
        return $fileFullUrl ? str_replace(config('other.IMAGE_URL'), '', $fileFullUrl) : '';
    }
}

if (!function_exists('getRequestFrom')) {
    /**
     * 判断请求来源
     */
    function getRequestFrom(): string
    {
        $middleware = request()->route()->middleware();
        //merchant来源
        if (in_array("merchantUserPermission", $middleware)) {
            return "merchant";
        }
        //运营端来源创建
        if (in_array("common.userPermissionAuth", $middleware)) {
            return "web";
        }
        //pos端来源创建
        if (in_array("pos.shopStatusAuth", $middleware)) {
            return "pos";
        }
        return "";
    }
}

if (!function_exists('formatDateYmd')) {
    /**
     * @param $time
     * @param string $default
     * @return string
     */
    function formatDateYmd($time, string $default = ""): string
    {
        return $time > 0 ? date("Y-m-d", $time) : $default;
    }
}

if (!function_exists("getSwitchCacheTime")) {
    /**
     * 根据不同环境获取缓存时间
     *
     * @param int $time
     * @return int
     */
    function getSwitchCacheTime(int $time): int
    {
        if (config('app.env') == 'prod' || config('app.env') == 'production') {
            return $time;
        }
        return 5;
    }
}

if (!function_exists('getFileSystem')) {

    /**
     * @return Filesystem
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    function getFileSystem(): Filesystem
    {
        return app()->get('files');
//        $dir                    = app()->storagePath() . "/" . date("Y-m-d");
//        if (!$fileSystem->isDirectory($dir)) {
//            $fileSystem->makeDirectory($dir, 0777, true);
//        }
    }
}

if (!function_exists('formatDate')) {
    /**
     * @param $time
     * @param string $default
     * @return string
     */
    function formatDate($time, string $default = '-'): string
    {
        return $time > 0 ? date("Y-m-d H:i:s", $time) : $default;
    }
}


if (!function_exists('objGetAttr')) {
    /**
     * @param null $obj
     * @param string $attr
     * @param string $default
     * @return string
     */
    function objGetAttr($obj, string $attr, string $default = ""): string
    {
        return collect($obj)->get($attr, $default);
    }
}

if (!function_exists("handleException")) {
    /**
     * 处理异常并返回客户端
     *
     * @param Exception $exception
     * @param string $msg
     * @param int|null $errorCode
     * @param array|null $logData
     * @param string $fsRobot
     * @throws BaseException
     */
    function handleException(
        Exception $exception,
        string $msg = "",
        int $errorCode = null,
        array $logData = null,
        string $fsRobot = SendFs::ROBOT_FS_BUSINESS_ERROR
    ) {
        if ($exception instanceof BaseException) {
            throw $exception;
        } else {
            if (in_array(config("app.env"), ["local"])) {
                logException($msg, $exception, $logData, true, true, $fsRobot);
                throw $exception;
            } else {
                logException($msg, $exception, $logData, true, true, $fsRobot);
                throw new BaseException($errorCode ?: BaseCodeEnum::ERR_SERVER_ERROR, $msg);
            }
        }
    }
}


if (!function_exists('logException')) {
    /**
     * @param string $title
     * @param Exception $exception
     * @param array|null $logParams
     * @param bool $logError
     * @param bool $fsNotify
     * @param string $fsRobot
     * @throws Exception
     */
    function logException(
        string $title,
        \Exception $exception,
        array $logParams = null,
        bool $logError = true,
        bool $fsNotify = false,
        string $fsRobot = SendFs::ROBOT_FS_BUSINESS_ERROR
    ): void {
        if ($fsNotify || $logError) {
            $msgCollection = new Collection([
                'time'      => formatDate(time()),
                "logTitle"  => $title,
                "file"      => $exception->getFile(),
                "line"      => $exception->getLine(),
                "msg"       => $exception->getMessage(),
                "logParams" => $logParams ?: null,
                'trace'     => $exception->getTraceAsString()
            ]);

            if ($fsNotify) {
                BuildFs::newRobot($fsRobot)
                       ->setTitleContent($title, $msgCollection->toJson(JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT))
                       ->send();
            }

            if ($logError) {
                Log::error($msgCollection->toJson(JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
            }
        }
    }
}

if (!function_exists('logMsg')) {
    /**
     * @param string $title
     * @param array|null $logParams
     * @param bool $logError
     * @param bool $fsNotify
     * @param string $robot
     */
    function logMsg(
        string $title,
        array $logParams = [],
        bool $logError = true,
        bool $fsNotify = false,
        string $robot = SendFs::ROBOT_WARNING
    ): void {
        if ($fsNotify || $logError) {
            $logContent = collect($logParams)->toJson(JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);

            if ($fsNotify) {
                SendFs::newRobot($robot)
                      ->setTitleContent($title, $logContent)
                      ->send();
            }

            if ($logError) {
                Log::error($title, $logParams);
            }
        }
    }
}

/**
 * 判断是否为json字符串
 */
if (!function_exists('isJsonStr')) {
    /**
     * @param string $str
     * @return bool
     */
    function isJsonStr(string $str): bool
    {
        return is_array(json_decode($str, true));
    }
}

/**
 * 枚举转select
 */
if (!function_exists('enumToSelection')) {
    /**
     * @param array $enum
     * @return array
     */
    function enumToSelection(array $enum): array
    {
        return collect($enum)->map(function ($v, $k) {
            return [
                "key"   => $v,
                "value" => $k
            ];
        })->values()->toArray();
    }
}

if (!function_exists('isTest')) {

    function isTest(): bool
    {
        if (config('app.env') == 'dev' || config('app.env') == 'qa') {
            return true;
        }

        return false;
    }
}
if (!function_exists('isProd')) {

    function isProd(): bool
    {
        if (config('app.env') == 'prod' || config('app.env') == 'production') {
            return true;
        }

        return false;
    }
}

if (!function_exists('bcdiv100')) {

    function bcdiv100($num): string
    {
        return bcdiv($num, 100, 2);
    }
}

if (!function_exists('bcmul100')) {

    function bcmul100($num): string
    {
        return bcmul($num, 100, 2);
    }
}


if (!function_exists("buildParsedUrl")) {
    /**
     * @param array|UriInterface $parsedUrl
     * @return string
     */
    function buildParsedUrl($parsedUrl): string
    {
        if ($parsedUrl instanceof Uri) {
            $parsedUrl = [
                "scheme"   => $parsedUrl->getScheme(),
                "host"     => $parsedUrl->getHost(),
                "port"     => $parsedUrl->getPort(),
                "path"     => $parsedUrl->getPath(),
                "query"    => $parsedUrl->getQuery(),
                "fragment" => $parsedUrl->getFragment(),
            ];
        }

        $url = '';

        if (!empty($parsedUrl['host'])) {
            if (!empty($parsedUrl['scheme'])) {
                $url .= $parsedUrl['scheme'] . ':';
            }

            $url .= '//' . trim($parsedUrl['host'], '/');
            if (!empty($parsedUrl['port'])) {
                $url .= ':' . $parsedUrl['port'];
            }
        }

        $url .= '/' . ltrim($parsedUrl['path'], '/');

        if (!empty($parsedUrl['query'])) {
            $url .= '?' . $parsedUrl['query'];
        }

        if (!empty($parsedUrl['fragment'])) {
            $url .= '#' . $parsedUrl['fragment'];
        }

        return $url;
    }
}

if (!function_exists("isJson")) {
    /**
     * @param String $jsonStr
     * @return bool
     */
    function isJson(string $jsonStr): bool
    {
        json_decode($jsonStr);
        if (json_last_error()) {
            return false;
        }
        return true;
    }
}

if (!function_exists("remoteContentsParser")) {
    /**
     * @param string $responseStr
     * @param null $default
     * @return mixed|null
     */
    function remoteContentsParser(string $responseStr, $default = null)
    {
        $xmlParser = xml_parser_create();
        if (xml_parse($xmlParser, $responseStr, true)) {
            $jsonStr = json_encode(simplexml_load_string($responseStr));
            return json_decode(str_replace(["\\n", PHP_EOL], "", $jsonStr), true);
        }

        return isJson($responseStr) ? json_decode($responseStr, true) : $default;
    }
}

if (!function_exists("jsonToArr")) {
    /**
     * @param String $jsonStr
     * @param null $default
     * @return mixed|null
     */
    function jsonToArr(string $jsonStr, $default = null)
    {
        return isJson($jsonStr) ? json_decode($jsonStr, true) : $default;
    }
}

if (!function_exists('translateEnumCodeToCn')) {
    /**
     * @param array $enum
     * @param int|string $code
     * @param string $default
     * @return string
     */
    function translateEnumCodeToCn(array $enum, $code, string $default = "-"): string
    {
        return $enum[$code] ?? $default;
    }
}

if (!function_exists("isFormatDate")) {
    /**
     * @param string $value
     * @param string $format
     * @return bool
     */
    function isFormatDate(string $value, string $format): bool
    {
        if (!is_string($value) && !is_numeric($value)) {
            return false;
        }
        $date = DateTime::createFromFormat('!' . $format, $value);
        if ($date && $date->format($format) == $value) {
            return true;
        }
        return false;
    }
}

if (!function_exists("attributeGet")) {
    /**
     * 多级属性值获取 ｜ 支持数组/对象/collection
     *
     * @param $original
     * @param $attribute
     * @param $default
     * @return mixed
     */
    function attributeGet($original, $attribute, $default)
    {
        if (is_null($attribute) || trim($attribute) === '') {
            return $original;
        }

        foreach (explode('.', $attribute) as $segment) {
            switch (strtolower(gettype($original))) {
                case "array":
                    if (!isset($original[$segment])) {
                        return value($default);
                    }
                    $original = $original[$segment];
                    break;
                case "object":
                    if ($original instanceof Collection) {
                        if (!$original->offsetExists($segment)) {
                            return value($default);
                        }
                        $original = $original->offsetGet($segment);
                    } else {
                        if (!is_object($original) || !isset($original->{$segment})) {
                            return value($default);
                        }
                        $original = $original->{$segment};
                    }
                    break;
                default:
                    return $default;
                    break;
            }
        }

        return $original;
    }
}

if (!function_exists("getTmpDir")) {
    /**
     * @param string $dir
     * @return string
     */
    function getTmpDir(string $dir): string
    {
        if (in_array(config("app.env"), ["local"])) {
            $basePath = storage_path();
        } else {
            $basePath = sys_get_temp_dir();
        }
        return vsprintf("%s/%s", [$basePath, trim($dir, "/")]);
    }
}


if (!function_exists("convertEncoding")) {
    /**
     * @param string $str
     * @param string $toEncoding
     * @return string
     */
    function convertEncoding(string $str, string $toEncoding = "UTF-8"): string
    {
        return mb_convert_encoding(
            $str,
            $toEncoding,
            mb_detect_encoding($str, array("ASCII", 'UTF-8', "GB2312", "GBK"))
        );
    }
}


